#include "event.h"


int epoll_init(int size)
{
   int ep = epoll_create(size);
   if(ep == -1)
      err_dump("epoll_init error");
   return ep;
}

int epoll_add(int ep,int fd,int event,int flags)
{
   int op , ret = -1;
   struct epoll_event ee;
   
   ee.events = event  | flags;
   ee.data.fd = fd;

   op = EPOLL_CTL_ADD;

   if((ret=epoll_ctl(ep,op,fd,&ee)) == -1)
      err_sys("epoll_ctl add event error");
   return ret;
}


int epoll_read(int fd,char **buf,int *len)
{
   //char *buf = *_buf; 
   printf("inner  methond buf:%p\n",*buf);
   int readn=0, total=0, avail = *len, oldsize= *len;
   *buf = (char*)thread_calloc(avail); 
   if(!*buf){
     err_ret("thread_calloc error");
     return -2;
   }
   printf("inner  methond2 buf:%p\n",*buf);
   while(1){
      if(readn == avail){
        *buf = thread_realloc(*buf,oldsize,oldsize+avail);
        if(!*buf){
          err_ret("thread_realloc error");
          return -2;
        }
        printf("inner  methond3 buf:%p\n",*buf);
        oldsize += avail;
      }
      readn = read(fd,*buf+total,avail); 
      if(readn<0){
        if(errno == EAGAIN || errno == EWOULDBLOCK){
           err_ret("read(%d) error again",fd);
           break;
        }
        err_ret("read(%d) error",fd);
        return -1;
      }else if(readn == 0){
        printf("has read zero total:%d\n",total);
        close(fd);
        return -1;
      }else if(readn > 0){
        total += readn; 
        if(readn == avail)
           continue;
        else
           break;
        printf("has read %d\n",readn);
      }
   }
   printf("has read at end total:%d\n",total);
   *len = total;
   return total; 
}

int epoll_wait_new_connect(int ep,int listen_fd,struct epoll_event *events,int maxevents,int timeout){
   int fdcnt = epoll_wait(ep,events,maxevents,timeout);
   int i , clientfd;
   
   for(i=0;i<fdcnt;i++){
      if(events[i].data.fd == listen_fd) {
         struct sockaddr_in client_addr;
         socklen_t  socklen;
         clientfd = accept(listen_fd,(struct sockaddr*)&client_addr,&socklen);
         if(clientfd < 0){
            err_ret("accept new connect err:");
            continue;
         } 

         setnonblocking(clientfd);
         
         epoll_add(ep,clientfd,EPOLLIN,EPOLLET);
      }/*else if(events[i].events & EPOLLIN){
         if((sockfd = events[i].data.fd)<0){
           err_msg("invalid new fd");
           continue; 
         }
       
         if
         
      }else if(events[i].events & EPOLLOUT){
      }*/ 
   } 
   return fdcnt;
}

int epoll_del(int ep,int fd)
{
   int op , ret = -1;
   struct epoll_event ee;
 
   op = EPOLL_CTL_DEL;  
 
   ee.events = 0;
   ee.data.fd = 0;
   
   if((ret=epoll_ctl(ep,op,fd,&ee)) == -1)    
      err_sys("epoll_ctl del event error");
   return ret;
}

int epoll_done(int ep)
{
  int ret = -1;
  if((ret=close(ep)) == -1)
     err_ret("close epoll fd");
  return ret; 
}
